#include "widget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QGridLayout>
#include <QLabel>
#include <QTextEdit>
#include <QLineEdit>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QPushButton>
#include <QCheckBox>
#include <QColorDialog>
#include <QJsonDocument>
#include <QDateTime>
#include <QRandomGenerator>
#include <QMessageBox>
#include <cmath>

Widget::Widget(QWidget *parent)
    : QWidget(parent),
      tcpSocket(new QTcpSocket(this)),
      autoSendTimer(new QTimer(this)),
      pointColor(Qt::red)
{
    setupUI();
    updateColorButton();

    // 网络连接信号槽
    connect(tcpSocket, &QTcpSocket::readyRead, this, &Widget::readData);
    connect(tcpSocket, &QTcpSocket::stateChanged, this, &Widget::connectionStateChanged);

    // 定时器信号槽
    connect(autoSendTimer, &QTimer::timeout, this, &Widget::generateRandomPoint);
}

Widget::~Widget()
{
    if (tcpSocket->state() == QAbstractSocket::ConnectedState) {
        tcpSocket->disconnectFromHost();
    }
}

void Widget::setupUI()
{
    // 主布局
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->setSpacing(10);
    mainLayout->setContentsMargins(10, 10, 10, 10);

    // 连接设置组
    QGroupBox *connectionGroup = new QGroupBox("服务器连接", this);
    QHBoxLayout *connectionLayout = new QHBoxLayout(connectionGroup);

    serverIpLineEdit = new QLineEdit("10.11.17.246", connectionGroup);
    serverPortSpinBox = new QSpinBox(connectionGroup);
    serverPortSpinBox->setRange(1024, 65535);
    serverPortSpinBox->setValue(8888);

    connectButton = new QPushButton("连接", connectionGroup);
    disconnectButton = new QPushButton("断开", connectionGroup);
    disconnectButton->setEnabled(false);

    connect(connectButton, &QPushButton::clicked, this, &Widget::connectToServer);
    connect(disconnectButton, &QPushButton::clicked, this, &Widget::disconnectFromServer);

    connectionLayout->addWidget(new QLabel("服务器IP:", connectionGroup));
    connectionLayout->addWidget(serverIpLineEdit);
    connectionLayout->addWidget(new QLabel("端口:", connectionGroup));
    connectionLayout->addWidget(serverPortSpinBox);
    connectionLayout->addWidget(connectButton);
    connectionLayout->addWidget(disconnectButton);
    connectionGroup->setLayout(connectionLayout);

    // 手动发送组
    QGroupBox *manualSendGroup = new QGroupBox("手动发送点数据", this);
    QGridLayout *manualSendLayout = new QGridLayout(manualSendGroup);

    manualXSpinBox = new QDoubleSpinBox(manualSendGroup);
    manualXSpinBox->setRange(-100, 100);
    manualXSpinBox->setDecimals(2);
    manualXSpinBox->setValue(0.0);

    manualYSpinBox = new QDoubleSpinBox(manualSendGroup);
    manualYSpinBox->setRange(-100, 100);
    manualYSpinBox->setDecimals(2);
    manualYSpinBox->setValue(0.0);

    manualDirectionSpinBox = new QDoubleSpinBox(manualSendGroup);
    manualDirectionSpinBox->setRange(0, 360);
    manualDirectionSpinBox->setDecimals(1);
    manualDirectionSpinBox->setValue(0.0);

    manualSpeedSpinBox = new QDoubleSpinBox(manualSendGroup);
    manualSpeedSpinBox->setRange(30, 60);
    manualSpeedSpinBox->setDecimals(1);
    manualSpeedSpinBox->setValue(0.0);

    manualSendButton = new QPushButton("发送点数据", manualSendGroup);
    connect(manualSendButton, &QPushButton::clicked, this, &Widget::sendManualPoint);

    manualSendLayout->addWidget(new QLabel("X坐标:", manualSendGroup), 0, 0);
    manualSendLayout->addWidget(manualXSpinBox, 0, 1);
    manualSendLayout->addWidget(new QLabel("Y坐标:", manualSendGroup), 1, 0);
    manualSendLayout->addWidget(manualYSpinBox, 1, 1);
    manualSendLayout->addWidget(new QLabel("方向(度):", manualSendGroup), 2, 0);
    manualSendLayout->addWidget(manualDirectionSpinBox, 2, 1);
    manualSendLayout->addWidget(new QLabel("速度:", manualSendGroup), 3, 0);
    manualSendLayout->addWidget(manualSpeedSpinBox, 3, 1);
    manualSendLayout->addWidget(manualSendButton, 4, 0, 1, 2);
    manualSendGroup->setLayout(manualSendLayout);

    // 自动发送组
    QGroupBox *autoSendGroup = new QGroupBox("自动发送设置", this);
    QHBoxLayout *autoSendLayout = new QHBoxLayout(autoSendGroup);

    autoSendIntervalSpinBox = new QSpinBox(autoSendGroup);
    autoSendIntervalSpinBox->setRange(100, 10000);
    autoSendIntervalSpinBox->setValue(2000);
    autoSendIntervalSpinBox->setSingleStep(100);

    randomColorCheckBox = new QCheckBox("随机颜色", autoSendGroup);
    randomColorCheckBox->setChecked(true);

    selectColorButton = new QPushButton("选择颜色", autoSendGroup);
    selectColorButton->setEnabled(false);

    startAutoSendButton = new QPushButton("开始自动发送", autoSendGroup);
    stopAutoSendButton = new QPushButton("停止自动发送", autoSendGroup);
    stopAutoSendButton->setEnabled(false);

    connect(randomColorCheckBox, &QCheckBox::stateChanged, this, &Widget::toggleRandomColor);
    connect(selectColorButton, &QPushButton::clicked, this, &Widget::selectColor);
    connect(startAutoSendButton, &QPushButton::clicked, this, &Widget::startAutoSending);
    connect(stopAutoSendButton, &QPushButton::clicked, this, &Widget::stopAutoSending);

    autoSendLayout->addWidget(new QLabel("间隔(毫秒):", autoSendGroup));
    autoSendLayout->addWidget(autoSendIntervalSpinBox);
    autoSendLayout->addWidget(randomColorCheckBox);
    autoSendLayout->addWidget(selectColorButton);
    autoSendLayout->addWidget(startAutoSendButton);
    autoSendLayout->addWidget(stopAutoSendButton);
    autoSendGroup->setLayout(autoSendLayout);

    // 状态和数据显示
    statusLabel = new QLabel("状态: 未连接", this);
    statusLabel->setAlignment(Qt::AlignCenter);

    textEdit = new QTextEdit(this);
    textEdit->setReadOnly(true);

    // 添加所有组件到主布局
    mainLayout->addWidget(connectionGroup);
    mainLayout->addWidget(manualSendGroup);
    mainLayout->addWidget(autoSendGroup);
    mainLayout->addWidget(statusLabel);
    mainLayout->addWidget(textEdit);

    setLayout(mainLayout);
    setWindowTitle("雷达点数据客户端");
    resize(650, 600);
}

void Widget::connectToServer()
{
    QHostAddress address(serverIpLineEdit->text());
    if (address.isNull()) {
        QMessageBox::warning(this, "错误", "无效的IP地址");
        return;
    }

    quint16 port = static_cast<quint16>(serverPortSpinBox->value());
    tcpSocket->connectToHost(address, port);
}

void Widget::disconnectFromServer()
{
    if (tcpSocket->state() == QAbstractSocket::ConnectedState) {
        tcpSocket->disconnectFromHost();
    }
}

void Widget::connectionStateChanged(QAbstractSocket::SocketState state)
{
    switch (state) {
    case QAbstractSocket::UnconnectedState:
        statusLabel->setText("状态: 未连接");
        connectButton->setEnabled(true);
        disconnectButton->setEnabled(false);
        stopAutoSending(); // 确保断开时停止自动发送
        break;
    case QAbstractSocket::ConnectingState:
        statusLabel->setText("状态: 连接中...");
        connectButton->setEnabled(false);
        disconnectButton->setEnabled(false);
        break;
    case QAbstractSocket::ConnectedState:
        statusLabel->setText("状态: 已连接");
        connectButton->setEnabled(false);
        disconnectButton->setEnabled(true);
        break;
    default:
        break;
    }
}

void Widget::readData()
{
    while (tcpSocket->bytesAvailable() > 0) {
        QByteArray data = tcpSocket->readAll();
        QJsonDocument doc = QJsonDocument::fromJson(data);
        if (!doc.isNull() && doc.isObject()) {
            displayPointData(doc.object());
        } else {
            textEdit->append("收到非JSON数据: " + data);
        }
    }
}

void Widget::sendManualPoint()
{
    QJsonObject pointData;
    pointData["x"] = QString::number(manualXSpinBox->value(), 'f', 2);
    pointData["y"] = QString::number(manualYSpinBox->value(), 'f', 2);
    pointData["direction"] = QString::number(manualDirectionSpinBox->value(), 'f', 1);
    pointData["speed"] = QString::number(manualSpeedSpinBox->value(), 'f', 1);

    if (randomColorCheckBox->isChecked()) {
        pointData["color"] = QColor(
            QRandomGenerator::global()->bounded(256),
            QRandomGenerator::global()->bounded(256),
            QRandomGenerator::global()->bounded(256)
        ).name();
    } else {
        pointData["color"] = pointColor.name();
    }

    pointData["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
    pointData["type"] = "manual";

    sendPointData(pointData);
}

void Widget::startAutoSending()
{
    if (tcpSocket->state() != QAbstractSocket::ConnectedState) {
        QMessageBox::warning(this, "错误", "未连接到服务器");
        return;
    }

    autoSendTimer->start(autoSendIntervalSpinBox->value());
    startAutoSendButton->setEnabled(false);
    stopAutoSendButton->setEnabled(true);
    statusLabel->setText("状态: 自动发送中...");
}

void Widget::stopAutoSending()
{
    autoSendTimer->stop();
    startAutoSendButton->setEnabled(true);
    stopAutoSendButton->setEnabled(false);
    statusLabel->setText("状态: 已连接");
}

void Widget::generateRandomPoint()
{
    QJsonObject pointData;
    pointData["x"] = QString::number(QRandomGenerator::global()->generateDouble() * 200 - 100, 'f', 2);
    pointData["y"] = QString::number(QRandomGenerator::global()->generateDouble() * 200 - 100, 'f', 2);
    pointData["direction"] = QString::number(QRandomGenerator::global()->generateDouble() * 360, 'f', 1);
    pointData["speed"] = QString::number(QRandomGenerator::global()->generateDouble() * 100, 'f', 1);

    if (randomColorCheckBox->isChecked()) {
        pointData["color"] = QColor(
            QRandomGenerator::global()->bounded(256),
            QRandomGenerator::global()->bounded(256),
            QRandomGenerator::global()->bounded(256)
        ).name();
    } else {
        pointData["color"] = pointColor.name();
    }

    pointData["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODateWithMs);
    pointData["type"] = "auto";

    sendPointData(pointData);
}

void Widget::sendPointData(const QJsonObject &pointData)
{
    if (tcpSocket->state() != QAbstractSocket::ConnectedState) {
        QMessageBox::warning(this, "错误", "未连接到服务器");
        return;
    }

    QByteArray data = QJsonDocument(pointData).toJson(QJsonDocument::Compact);
    qint64 bytesSent = tcpSocket->write(data);

    if (bytesSent == -1) {
        statusLabel->setText("发送失败: " + tcpSocket->errorString());
    } else {
        statusLabel->setText(QString("最后发送时间: %1").arg(
            QDateTime::currentDateTime().toString("hh:mm:ss.zzz")));
    }
}

QString Widget::convertDirection(double degrees)
{
    degrees = fmod(degrees, 360.0);
    if (degrees < 0) degrees += 360.0;

    if (degrees >= 0 && degrees < 90) {
        return QString("东偏北%1°").arg(QString::number(90 - degrees, 'f', 1));
    } else if (degrees >= 90 && degrees < 180) {
        return QString("西偏北%1°").arg(QString::number(degrees - 90, 'f', 1));
    } else if (degrees >= 180 && degrees < 270) {
        return QString("西偏南%1°").arg(QString::number(270 - degrees, 'f', 1));
    } else {
        return QString("东偏南%1°").arg(QString::number(degrees - 270, 'f', 1));
    }
}

void Widget::displayPointData(const QJsonObject &pointData)
{
    double direction = pointData["direction"].toString().toDouble();
    QString directionStr = convertDirection(direction);

    QString info = QString("收到点数据:\n"
                         "X坐标: %1\n"
                         "Y坐标: %2\n"
                         "方向: %3\n"
                         "速度: %4\n"
                         "颜色: %5\n"
                         "时间戳: %6\n"
                         "类型: %7\n"
                         "-------------------")
                  .arg(pointData["x"].toString())
                  .arg(pointData["y"].toString())
                  .arg(directionStr)
                  .arg(pointData["speed"].toString())
                  .arg(pointData["color"].toString())
                  .arg(pointData["timestamp"].toString())
                  .arg(pointData.contains("type") ? pointData["type"].toString() : "unknown");

    textEdit->append(info);
}

void Widget::selectColor()
{
    QColor newColor = QColorDialog::getColor(pointColor, this, "选择点颜色");
    if (newColor.isValid()) {
        pointColor = newColor;
        updateColorButton();
    }
}

void Widget::toggleRandomColor(int state)
{
    selectColorButton->setEnabled(state == Qt::Unchecked);
}

void Widget::updateColorButton()
{
    QPixmap pixmap(16, 16);
    pixmap.fill(pointColor);
    selectColorButton->setIcon(QIcon(pixmap));
}
